﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using Slippor.Utility.WebWorker;

namespace Slippor.Douban.Radio.Assist
{
    public class DoubanAccount
    {
        public const String SessionKey = "ck";
        public const String EmailKey = "ue";
        public const String IDKey = "dbcl2";

        public String Name { get; set; }
        public DoubanCookie Cookie { get; set; }
        public bool IsLoged 
        {
            get
            {
                return Cookie.ContainsKey(SessionKey);
            }
        }

        public String CurrentSession
        {
            get
            {
                if (Cookie.ContainsKey(SessionKey))
                {
                    return Cookie[SessionKey];
                }
                else
                {
                    return String.Empty;
                }
            }
            set
            {
                if (value != null)
                {
                    Cookie[SessionKey] = value;
                }
                else if (Cookie.ContainsKey(SessionKey))
                {
                    Cookie.Remove(SessionKey);
                }
            }
        }

        public String Email
        {
            get
            {
                if (Cookie.ContainsKey(EmailKey))
                {
                    return Cookie[EmailKey];
                }
                else
                {
                    return String.Empty;
                }
            }
        }

        public String ID
        {
            get
            {
                if (Cookie.ContainsKey(IDKey))
                {
                    return Cookie[IDKey];
                }
                else
                {
                    return String.Empty;
                }
            }
            set
            {
                if (value != null)
                {
                    Cookie[IDKey] = value;
                }
                else if (Cookie.ContainsKey(IDKey))
                {
                    Cookie.Remove(IDKey);
                }
            }
        }

        public bool IsLoginWithID 
        { 
            get
            {
                return Cookie.ContainsKey(IDKey);
            }
        }

        public static DoubanAccount UnLogedAccount
        {
            get
            {
                return new DoubanAccount
                           {
                               Cookie = new DoubanCookie(),
                               Name = String.Empty,
                               LogState = LogState.Idle,
                           };
            }
        }

        public LogState LogState
        {
            get; set;
        }
    }

    public class DoubanCookie : Dictionary<String, String>
    {
        public String CookieString
        {
            get { return _cookieString; }
            set
            {
                Clear();
                _cookieString = value;
                if(!String.IsNullOrEmpty(_cookieString))
                {
                    String[] cookStrs = _cookieString.Split(';');
                    foreach (string str in cookStrs)
                    {
                        if(!String.IsNullOrEmpty(str))
                        {
                            String[] cookieNameValue = str.Split('=');
                            if (cookieNameValue != null && cookieNameValue.Length > 1 && cookieNameValue[0].IndexOf("__utm") != 0 && cookieNameValue[0].IndexOf("__gads") != 0)
                            {
                                Add(cookieNameValue[0].Trim(), cookieNameValue[1].Trim());
                            }
                        }
                    }
                }
            }
        }

        private String _cookieString;

        public String Session
        {
            get 
            {
                if (ContainsKey(DoubanAccount.SessionKey))
                {
                    return this[DoubanAccount.SessionKey];
                }
                else
                {
                    return String.Empty;
                }
            }
        }
    }

    public static class AccountControl
    {
        private const String _doubanUrl = "http://douban.fm/";
        private const String _accountPattern = "class=\"login\"[\\w\\W]*?\x6b22\x8fce[\\w\\W]*?href=\"http://www.douban.com/people/(?<id>[^/]+)/\">(?<name>[\\w\\W]*?)</a>[\\w\\W]*?(?<logout>http://www.douban.com/accounts/logout\\?ck=[^\"]+)";

        public static DoubanAccount GetAccount(byte[] loginData)
        {
            int tryTime = 10;
            using (var webWorker = new DoubanWebWorker())
            {
                String cookie = webWorker.Login(loginData);
                while (tryTime > 0 && !String.IsNullOrEmpty(cookie))
                {
                    try
                    {
                        String doc = webWorker.AchieveResponse(_doubanUrl, null, cookie, true, RequestMethod.Get);
                        DoubanAccount account = GetAccount(doc, new DoubanCookie { CookieString = cookie });
                        tryTime = 0;
                        return account;
                    }
                    catch
                    {
                        tryTime--;
                        Thread.Sleep(1000);
                    }
                }
            }
            return DoubanAccount.UnLogedAccount;
        }

        public static DoubanAccount GetAccount(String doc, DoubanCookie cookie)
        {
            DoubanAccount account = new DoubanAccount { Cookie = cookie };
            Match match = Regex.Match(doc, _accountPattern);
            if (match.Success)
            {
                String name = match.Groups["name"].Value;
                account.Name = name;
            }
            else
            {
                account.CurrentSession = null;
            }
            return account;
        }
    }

    public enum LogState
    {
        Idle,
        Logging,
    }
}
